package com.hx.zhg.service.system.impl;

import com.hx.zhg.constant.CacheManagerConstant;
import com.hx.zhg.constant.CacheNameConstant;
import com.hx.zhg.exception.BusinessException;
import com.hx.zhg.service.quartz.WxFlushAccessTokenJob;
import com.hx.zhg.service.system.WxSystemService;
import com.hx.zhg.service.system.common.JsapiTicketUtil;
import com.hx.zhg.service.system.common.WxSystemCommon;
import com.hx.zhg.service.system.vo.AccessTokenVo;
import com.hx.zhg.service.system.vo.JSSDKConfigVo;
import com.hx.zhg.util.HttpClientUtil;
import com.hx.zhg.util.JsonUtils;
import com.hx.zhg.util.SHA1Util;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.Map;

/**
 * Created by zhenghegong on 2020/4/19.
 */
@Service("wxSystemService")
public class WxSystemServiceImpl implements WxSystemService {

    private static final Logger log = Logger.getLogger(WxSystemServiceImpl.class);

    @Value("${hx.wx.token.url}")
    public String tokenUrl;
    @Value("${hx.wx.appid}")
    public String appId;
    @Value("${hx.wx.grantType}")
    public String grantType;
    @Value("${hx.wx.secret}")
    public String secret;
    @Value("${hx.wx.token}")
    public String token;
    @Value("${hx.wx.getPageAccessTokenUrl}")
    public String getPageAccessTokenUrl;

    @Override
    public String getAccessToken() throws Exception {
        String url = String.format("%s?grant_type=%s&appid=%s&secret=%s", tokenUrl, grantType, appId, secret);
        String result = HttpClientUtil.doHttpGetRequest(url);
        return result;
    }

    /**
     * 缓存的key是不变的，因为当前只有一个微信公众号
     *
     * @throws Exception
     */
    @CachePut(cacheManager = CacheManagerConstant.ACCESS_TOKEN_CACHE_MANAGER, value = CacheNameConstant.ACCESS_TOKEN_CACHE, key = "T(String).valueOf('" + CacheNameConstant.ACCESS_TOKEN_CACHE_PREFIX + "').concat('hx')")
    @Override
    public String flushAccessToken() throws Exception {
        log.info("【*】执行 >> flushAccessToken << ");
        String accessToken = getAccessToken();
        AccessTokenVo accessTokenVo = JsonUtils.jsonToObj(accessToken, AccessTokenVo.class);
        if (accessTokenVo == null) {
            throw new BusinessException("获取ACCESS_TOKEN请求错误：accessTokenVo is null");
        }
        if (accessTokenVo.getErrcode() != null) {
            throw new BusinessException("获取ACCESS_TOKEN请求错误：" + accessTokenVo.getErrmsg());
        }
        return accessTokenVo.getAccess_token();
    }

    @Cacheable(cacheManager = CacheManagerConstant.ACCESS_TOKEN_CACHE_MANAGER, value = CacheNameConstant.ACCESS_TOKEN_CACHE, key = "T(String).valueOf('" + CacheNameConstant.ACCESS_TOKEN_CACHE_PREFIX + "').concat('hx')")
    @Override
    public String getCacheAccessToken() throws Exception {
        return null;
    }

    @Override
    public boolean checkSignature(String signature, String timestamp, String nonce) throws Exception {
        if (StringUtils.isNotBlank(signature) &&
                StringUtils.isNotBlank(timestamp) &&
                StringUtils.isNotBlank(nonce)) {
            return WxSystemCommon.checkSignature(signature, timestamp, nonce, token);
        }
        return false;
    }

    @Override
    public JSSDKConfigVo getJSSDKConfig(String url) throws Exception {
        //随机字符串
        String noncestr = WxSystemCommon.generate(19);
        //事件戳
        String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
        //获取ACCESS_TOKEN
        String cacheAccessToken = ((WxSystemService) AopContext.currentProxy()).getCacheAccessToken();
        if (cacheAccessToken == null) {
            throw new BusinessException("获取缓存ACCESS_TOKEN失败");
        }
        //获取ticket
        Map<String, String> stringStringMap = JsapiTicketUtil.jsapiTicket(cacheAccessToken, getPageAccessTokenUrl);
        String ticket = stringStringMap.get("ticket");
        //将参数排序并拼接字符串
        String str = "jsapi_ticket=" + ticket + "&noncestr=" + noncestr + "&timestamp=" + timestamp + "&url=" + url;
        String signature = SHA1Util.encrypt(str);
        return new JSSDKConfigVo(appId, timestamp, noncestr, signature);
    }
}
